home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / Tumbler and Podium / Tumbler_AEVT.c < prev    next >
Encoding:
Text File  |  1995-06-08  |  22.0 KB  |  831 lines  |  [TEXT/MPS ]

  1. //    Tumbler_AEVT.c
  2. //
  3. //    Apple Event Routines for the Tumbler App.  Contains AppleEvent Handlers and senders for
  4. //  the Tumbler app.
  5. //        
  6. //    Author:        Nick Thompson, 11/24/94
  7. //
  8. //    Modification History:
  9. //
  10. //    11/26/94        nick        clean up, remove old TE references from dragtext, remove
  11. //                                all other dead code
  12. //    11/24/94        nick        Initial Cut - factored code from Tumbler event, added
  13. //                                 Drag related events for debugging (you can't debug the 
  14. //                                handler, but if the handler sends an event you can debug
  15. //                                the AE handler).
  16. //
  17. //    Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
  18. //
  19. //    To Do:
  20. //        a number of items are "duplicated" in the event we send to ourselves
  21. //        we send the window and the document (the doc reference is stored in the
  22. //        window refcon, window is stored in the doc)
  23. //
  24.  
  25. #include <AppleEvents.h>
  26. #include <Drag.h>
  27. #include <GestaltEqu.h>
  28. #include <Memory.h>
  29. #include <SegLoad.h>
  30.  
  31. #include "Tumbler_prototypes.h"
  32. #include "Tumbler_resources.h"
  33. #include "Tumbler_offscreen.h"
  34. #include "Tumbler_globals.h"
  35.  
  36. #include "Tumbler_AEVT.h"
  37. #include "Tumbler_Traps.h"
  38. #include "Tumbler_Document.h"
  39. #include "Tumbler_file.h"
  40. #include "Tumbler_PICTImport.h"
  41. #include "Tumbler_camera.h"
  42. #include "Tumbler_file.h"
  43.  
  44. #ifdef PODIUM_APP
  45. #include "Tumbler_Podium.h"
  46. #endif
  47.  
  48. #include "QD3D.h"
  49. #include "QD3DDrawContext.h"
  50. #include "QD3DGroup.h"
  51. #include "QD3DIO.h"
  52. #include "QD3DPick.h"
  53. #include "QD3DShader.h"
  54. #include "QD3DStorage.h"
  55. #include "QD3DTransform.h"
  56. #include "QD3DView.h"
  57.  
  58.  
  59. #define    kGestaltTrap    0xA0AD
  60.  
  61. #include "Tumbler_AEVT.h"
  62.  
  63.  
  64. // local variables - to this file
  65.  
  66. static AEAddressDesc        pSelfAddress;            // A self-addressed address descriptor record
  67. static ProcessSerialNumber    pSelfPSN;                // This application's psn
  68. static AEDesc                pnilDesc;                // A nil descriptor record
  69.  
  70. // this defines a suite of events for dispatching drags
  71. static const AEEventClass    kDraggingClass             = 'drag' ;
  72.     static const AEEventID        kDragDrawID                = 'draw' ;
  73.     static const AEEventID        kDragSendID                = 'send' ;
  74.     static const AEEventID        kDragReceiveID            = 'recv' ;
  75.     static const AEEventID        kDragTrackID            = 'trak' ;
  76.     static const AEEventID        kDragDragID                = 'drag' ;
  77.     
  78. //
  79.  
  80. static const AEKeyword    keyPrivateData                = 'priv' ;
  81.  
  82.  
  83. // AppleEvent Error Handling....
  84. //----------------------------------------------------------------------------------
  85. //  If an error has occurred, I check the user interaction level. If I can            
  86. //    interact with the user, I put up a dialog and exit the application; otherwise,
  87. //    I just exit the application.
  88. //
  89. //    ***NOTE: Real applications would not handle errors in this fashion!  If they
  90. //    cannot interact with the user, they should abort the Apple event handler and
  91. // return the error in the reply parameter.
  92.  
  93. void FailIfErr (OSErr  error)
  94. {
  95.     OSErr        interactErr = noErr ;
  96.     if (error != noErr)
  97.     {
  98.         if ((interactErr = AEInteractWithUser(kNoTimeOut, nil, nil)) == noErr) {    
  99.                                     // Can we interact?
  100.             AlertUser(error);        // Yes, so put up the dialog.
  101.             ExitToShell();
  102.         }
  103.     }
  104. }
  105.  
  106. //----------------------------------------------------------------------------------
  107. // Display an alert for the user to indicate that an error has occurred.
  108. // This approach would not really be good for a real app - hard coding 
  109. // strings in this manner would be really hard to localise.     But this approach
  110. // is good for programming because it gives us the error code.    
  111.  
  112. void AlertUser (short  error)
  113. {
  114.     short        itemHit;
  115.     Str255        defaultMessage = "\pAn error was encountered" ;
  116.     Str255        message ;
  117.     Str255        errNo ;
  118.  
  119.     if( error < 0 ) {
  120.         BlockMove( &defaultMessage[1], &message[1], defaultMessage[0] );
  121.         message[0] = defaultMessage[0] ;
  122.     }
  123.     else {
  124.         GetIndString(message, rErrorStringIndex, error);
  125.     }
  126.     
  127.     NumToString( error, errNo ) ;
  128.     
  129.     ParamText(    message,
  130.                 (ConstStr255Param)"\p (",
  131.                 errNo,
  132.                 (ConstStr255Param)"\p).");    // [pwpc]
  133.  
  134.     itemHit = Alert(rUserAlert, nil);
  135. }
  136.  
  137. //----------------------------------------------------------------------------------
  138.  
  139. void    FatalError(short error)
  140. {
  141.  
  142.     Str255        message ;
  143.  
  144.     GetIndString(message, rFatalErrorStringIndex, error);
  145.     ParamText(message, (ConstStr255Param)"\p", (ConstStr255Param)"\p", (ConstStr255Param)"\p");    // [pwpc]
  146.     (void)StopAlert( rFatalAlert, nil ) ;
  147.     ExitToShell() ;
  148. }
  149.  
  150. //-----------------------------------------------------------------------
  151. // call this to init the AE stuff in this file
  152.  
  153. void InitAEStuff( void ) 
  154. {
  155.     // Set up the self-addressed descriptor record.
  156.     pSelfPSN.highLongOfPSN = 0;
  157.     pSelfPSN.lowLongOfPSN = kCurrentProcess;        // Use this instead of GetCurrentProcess
  158.     FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&pSelfPSN,sizeof(ProcessSerialNumber),&pSelfAddress));
  159.     pnilDesc.descriptorType = typeNull;            // Initialize the global nil descriptor record.
  160.     pnilDesc.dataHandle = nil;
  161.     
  162.     RegisterMyEvents() ;                            // and finally register appleEvent handlers
  163.     
  164. }
  165.  
  166. //-----------------------------------------------------------------------
  167. // returns true if the platform supports appleevents - we won't run
  168. // if it doesn't
  169.  
  170. Boolean SupportsAEVT(void)
  171. {
  172.     OSErr err;
  173.     long response;
  174.     
  175.     if (!myTrapAvailable(kGestaltTrap))
  176.         return false;
  177.     
  178.     err = Gestalt(gestaltAppleEventsAttr,&response);
  179.     if (err!=noErr)
  180.         return false;
  181.         
  182.     return (response && (response << gestaltAppleEventsPresent));
  183. }
  184.  
  185. //-----------------------------------------------------------------------
  186. // called to process high level appleevents
  187.  
  188. void DoHighLevelEvent(EventRecord *ev)
  189. {
  190.     OSErr err;
  191.     
  192.     err = AEProcessAppleEvent(ev);    
  193. }
  194.  
  195. //-----------------------------------------------------------------------
  196. // called to register our appleevent handlers
  197.  
  198. void RegisterMyEvents(void)
  199. {
  200.     OSErr err;
  201.     
  202.     if (!SupportsAEVT())
  203.         return;
  204.     
  205.     err = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,NewAEEventHandlerProc(MyAEHandleOAPP),0L,false);
  206.     if (err!=noErr)
  207.         return;
  208.                 
  209.     err = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,NewAEEventHandlerProc(MyAEHandleODOC),0L,false);
  210.     if (err!=noErr)
  211.         return;
  212.                 
  213.     err = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,NewAEEventHandlerProc(MyAEHandlePDOC),0L,false);
  214.     if (err!=noErr)
  215.         return;
  216.                 
  217.     err = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,NewAEEventHandlerProc(MyAEHandleQUIT),0L,false);
  218.     if (err!=noErr)
  219.         return;            
  220.  
  221.  
  222.     // drag stuff handlers
  223.     err = AEInstallEventHandler(kDraggingClass,kDragReceiveID,NewAEEventHandlerProc(MyAEHandleDragRecv),0L,false);
  224.     if (err!=noErr)
  225.         return;            
  226.  
  227. }
  228.  
  229. //-----------------------------------------------------------------------
  230. // open application event handler for the core event suite, 
  231. // by default we just want a blank new document
  232.  
  233. pascal OSErr MyAEHandleOAPP(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  234. {
  235.     OSErr err = noErr ;
  236.  
  237. #ifndef PODIUM_APP
  238.     DoNewDocument();
  239. #endif
  240.     return err;
  241. }
  242.  
  243.  
  244. //-----------------------------------------------------------------------
  245. // handler for the open document appleevent handler
  246.  
  247. pascal OSErr MyAEHandleODOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  248. {
  249.     FSSpec         myFSS;
  250.     AEDescList    docList;
  251.     OSErr        err,
  252.                 ignoreErr;
  253.     long        index,
  254.                 itemsInList;
  255.     Size         actualSize;
  256.     AEKeyword    keywd;
  257.     DescType    returnedType;
  258.  
  259.     
  260.     err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList);
  261.     if (err == noErr) {
  262.     
  263.         // see how many descriptor items are in the list
  264.         // this is the number of documents we want to open
  265.         err = AECountItems(&docList,&itemsInList);
  266.  
  267.         // now get each descriptor record from the list
  268.         // coerce the returned data to an FSSpec record, and
  269.         // open the asoociated file
  270.         
  271.         for (index=1; index <= itemsInList && err == noErr; index++) {
  272.         
  273.             err = AEGetNthPtr(    &docList, 
  274.                                 index,
  275.                                 typeFSS,
  276.                                 &keywd,
  277.                                 &returnedType,
  278.                                 (Ptr)&myFSS,
  279.                                 sizeof(myFSS),
  280.                                 &actualSize);
  281.     
  282.             if (err == noErr)    {
  283.             
  284.                 FInfo        fndrInfo ;
  285.                 
  286.                 // we now have a valid FSSpec to reference the file, we need to know 
  287.                 // what type the file is to determine which file open function to call
  288.                 // we can determine this from the finder info for the file
  289.                 
  290.                 err = FSpGetFInfo( &myFSS, &fndrInfo );    
  291.                 
  292.                 // if we got that ok, then we switch on the file  
  293.                 // type (we don't care about the creator type)    
  294.                         
  295.                 if (err == noErr)    {
  296.                 
  297.                     switch( fndrInfo.fdType ) {
  298.                         case 'PICT':
  299.                             break ;
  300.                             
  301.                         case 'TEXT':
  302.                         case '3DMF':
  303.                             err = DoOpenFile(&myFSS);
  304.                             break ;
  305.                         
  306.                         default:
  307.                             break ;
  308.                     }
  309.                 }
  310.             }
  311.         }
  312.         ignoreErr = AEDisposeDesc(&docList);
  313.     }
  314.     return err ;
  315. }
  316.  
  317. //-----------------------------------------------------------------------
  318. // handler for the print document event handler
  319.  
  320. pascal OSErr MyAEHandlePDOC(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  321. {
  322.     FSSpec         myFSS;
  323.     AEDescList    docList;
  324.     OSErr        err;
  325.     long        index,
  326.                 itemsInList;
  327.     Size         actualSize;
  328.     AEKeyword    keywd;
  329.     DescType    returnedType;
  330.  
  331.     
  332.     err = AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,&docList);
  333.     if (err == noErr) {
  334.     
  335.         // see how many descriptor items are in the list
  336.         // this is the number of documents we want to open
  337.         err = AECountItems(&docList,&itemsInList);
  338.  
  339.         // now get each descriptor record from the list
  340.         // coerce the returned data to an FSSpec record, and
  341.         // open the asoociated file
  342.         
  343.         for (index=1; index <= itemsInList && err == noErr; index++) {
  344.         
  345.             err = AEGetNthPtr(    &docList, 
  346.                                 index,
  347.                                 typeFSS,
  348.                                 &keywd,
  349.                                 &returnedType,
  350.                                 (Ptr)&myFSS,
  351.                                 sizeof(myFSS),
  352.                                 &actualSize);
  353.     
  354.             if (err == noErr)    {                    
  355.                 // err = HandlePrintDoc( &myFSS );
  356.                 err = errAEEventNotHandled ;         // we don't do this yet...
  357.             }
  358.         }
  359.         err = AEDisposeDesc(&docList);
  360.     }
  361.     return err ;
  362. }
  363.  
  364. //-----------------------------------------------------------------------
  365. // quit appleevent handler
  366.  
  367. pascal OSErr MyAEHandleQUIT(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  368. {
  369.     OSErr             err = noErr ;        // used as return value
  370.  
  371.     
  372.     // close all windows and signal to Quit
  373.  
  374.     gQuitting = true;
  375.         
  376.     // attempt to close all documents
  377.     if( CloseAllDocuments() == false )
  378.         return userCanceledErr ;    // couldn't close them, so indicate the user cancelled
  379.         
  380.  
  381.     // if we closed everything up successfully, we can return noErr, otherwise
  382.     // indicate to sender of the 'quit' aevt that we canceled
  383.     
  384.     if (gQuitting) {
  385.         gQuit = true;                        // user didn't cancel
  386.         err = AEDisposeDesc(&pSelfAddress);    // Dispose of my self-addressed descriptor.
  387.     }
  388.     else {
  389.         err = userCanceledErr ;
  390.     }
  391.             
  392.     return err ;
  393. }
  394.  
  395. //-----------------------------------------------------------------------
  396. // drag receive appleevent handler
  397.  
  398. pascal OSErr MyAEHandleDragRecv(AppleEvent *theAppleEvent,AppleEvent *reply,long refCon)
  399. {
  400.  
  401.     AEDesc                myDesc;
  402.     OSErr                err;
  403.     OSErr                ignoreErr ;
  404.     TQ3Object             objects = nil;
  405.  
  406.  
  407.     err = AEGetParamDesc(theAppleEvent,keyPrivateData,typeChar,&myDesc);
  408.     if (err == noErr) {
  409.     
  410.         // try to load all of the items we stuffed into the apple event
  411.         myPrivateDataHdl        thePrivateData = (myPrivateDataHdl)myDesc.dataHandle ;
  412.         OSType                    theDragType = (**thePrivateData).myTypeOfData ;
  413.         DocumentPtr             theDocument = (**thePrivateData).myDocument ;
  414.         long                    dataSize = (**thePrivateData).myDataSize ;
  415.         WindowPtr                theWindow = (**thePrivateData).myWindow  ;
  416.         Point                    theLocation = (**thePrivateData).myLocation ;
  417.         Handle                    dataHdl = NewHandle( dataSize ) ;
  418.         
  419.         // sanity check
  420.         if( dataSize > GetHandleSize( myDesc.dataHandle )) {
  421.             ignoreErr = AEDisposeDesc(&myDesc);
  422.             return paramErr ;
  423.         }
  424.         
  425.         // check we could create the data handle OK
  426.         if( dataHdl == nil ) {
  427.             ignoreErr = AEDisposeDesc(&myDesc);
  428.             return MemError() ;
  429.         }
  430.  
  431.         // copy the data from the descriptor to our handle
  432.         BlockMove( &(**thePrivateData).myData, *dataHdl, dataSize );
  433.         
  434.         // we need to get rid of the descriptor, to save on memory
  435.         err = AEDisposeDesc(&myDesc);
  436.         
  437.         // process the information from the drag
  438.         if( theDragType == '3DMF' ) {
  439.         
  440.             TQ3SharedObject    viewHints ;
  441.         
  442.             // do this on receipt of a drag of type 3DMF    
  443.  
  444.             TQ3FileObject         fd;
  445.             TQ3StorageObject         storage;
  446.  
  447.             // Lock and load
  448.             MoveHHi( dataHdl ) ;
  449.             HLock(  dataHdl ) ;
  450.             
  451.             storage = Q3MemoryStorage_New((const unsigned char *) *dataHdl,
  452.                 (unsigned long) dataSize );
  453.                 
  454.             HUnlock( dataHdl ) ;
  455.             
  456.             if (storage == nil)
  457.                 goto bail;
  458.             
  459.             fd = Q3File_New();
  460.             Q3File_SetStorage(fd, storage);
  461.             Q3Object_Dispose(storage);
  462.             
  463.             if (fd == nil)
  464.                 goto bail;
  465.  
  466.             Tumbler_ReadScene(
  467.                 fd,
  468.                 false,
  469.                 &viewHints,
  470.                 &theDocument->documentGroup) ;
  471.                 
  472.             TumblerDocument_UpdateView( theDocument,  viewHints ) ;
  473.  
  474. #ifdef PODIUM_APP
  475.             {
  476.             // we really want the obect to be centered about the 
  477.             // drop location.
  478.             GrafPtr        savedPort ;
  479.             
  480.             extern void Podium_UpdateDrawContextFromDropRect( DocumentPtr theDocument ) ;
  481.  
  482.             GetPort( &savedPort ) ;
  483.             SetPort( theWindow ) ;
  484.             GlobalToLocal(&theLocation) ;
  485.             
  486.             // make the droprect be located top left at (0, 0)
  487.             OffsetRect( &theDocument->dropArea, -theDocument->dropArea.left,  -theDocument->dropArea.top );
  488.             OffsetRect( &theDocument->dropArea, 
  489.                             (theLocation.h - ((theDocument->dropArea.right - theDocument->dropArea.left)/2)), 
  490.                             (theLocation.v - ((theDocument->dropArea.bottom - theDocument->dropArea.top)/2)) );
  491.             Podium_UpdateDrawContextFromDropRect( theDocument ) ;
  492.             SetPort(savedPort) ;
  493.             }
  494. #endif
  495.             
  496.             TumblerDocument_UpdateView( theDocument, viewHints ) ;
  497.             
  498.             AdjustLightsPositions(theDocument) ;
  499.         
  500.             if (viewHints)
  501.                 Q3Object_Dispose(viewHints);
  502.         
  503.             Q3Object_Dispose(fd);
  504.         }        
  505.         else if( theDragType == 'PICT' ){
  506.  
  507.             // do this on receipt of a drag of type PICT
  508.  
  509.             TQ3StoragePixmap textureImage;
  510.             PicHandle        thePicture = (PicHandle)dataHdl ;
  511.  
  512.             //Create a texture pixmap
  513.             MoveHHi((Handle) thePicture );
  514.             HLock((Handle) thePicture );
  515.  
  516.             if( TextureFromPICT((PicHandle) thePicture, &textureImage) == kQ3False ) {
  517.                 Alert(130, 0L);
  518.                 goto bail;
  519.             }
  520.             
  521.             if( AddTextureToDocument( theDocument, &textureImage) != kQ3Success ) {
  522.                 Alert(130, 0L);
  523.                 goto bail;
  524.             }
  525.             HUnlock((Handle)thePicture);
  526.             
  527.         }        
  528.         else if( theDragType == flavorTypeHFS ){
  529.         
  530.             // do this on receipt of an HFS flavor (a file from the finder)
  531.             HFSFlavor        theHFSFlavor ;
  532.  
  533.             // lock down the handle
  534.             MoveHHi( dataHdl ) ;
  535.             HLock( dataHdl ) ;
  536.             
  537.             theHFSFlavor = *((HFSFlavor *)*dataHdl) ;
  538.  
  539.             
  540.             if( theHFSFlavor.fileType == 'TEXT' || theHFSFlavor.fileType == '3DMF') {
  541.             
  542.                 OSErr                result;
  543.                 short                refNum;
  544.                 DocumentPtr         theDocument;
  545.                 FInfo                fndrInfo ;
  546.                 TQ3Boolean            isText ;
  547.             
  548.                 // we assume the FSSpec passed in was valid, get the file information
  549.                 // we need to know the file type, this routine may get called by an appleEvent
  550.                 // handler, so we can't assume a type, we need to get it from the fsspec.
  551.                 
  552.                 FSpGetFInfo( &theHFSFlavor.fileSpec, &fndrInfo ) ;
  553.                 
  554.                 // pull out the file type
  555.                 
  556.                 isText = ( fndrInfo.fdType == 'TEXT') ;
  557.                 
  558.                 if ((result = FSpOpenDF(&theHFSFlavor.fileSpec, fsRdWrPerm, &refNum)) != noErr)
  559.                     return(result);
  560.         
  561.                 theDocument->fRefNum = refNum;
  562.                 theDocument->theFileSpec = theHFSFlavor.fileSpec ;
  563.                 SetCursor(*GetCursor(watchCursor));
  564.                 ReadDocumentFile( theDocument, isText ) ;
  565.                 SetCursor(&qd.arrow);
  566.             
  567.             } else if( theHFSFlavor.fileType == 'PICT' && theDocument && theDocument->documentGroup) {
  568.  
  569.                 PicHandle        thePict;
  570.                 TQ3StoragePixmap textureImage;
  571.                 
  572.                 // get the picture from the file
  573.                 thePict = OpenPICTFile(&theHFSFlavor.fileSpec);
  574.                 
  575.                 // make a texture
  576.                 TextureFromPICT( thePict, &textureImage);
  577.                 AddTextureToDocument( theDocument, &textureImage);
  578.                 
  579.                 // and free the space occupied by the picture
  580.                 KillPicture(thePict) ;
  581.             
  582.             }
  583.             else
  584.                 dataSize = 0;    // need better handling here...
  585.         
  586.         
  587.         }
  588.  
  589.         // we can free up the memory now...
  590.         DisposeHandle( dataHdl ) ;
  591.         dataHdl = nil ;
  592.         
  593.         //    If we actually received something, insert it into the destination.
  594.     
  595.         if (dataSize != 0) {
  596.     
  597.             theDocument->dirty = true;
  598.                 AdjustLightsPositions( theDocument);
  599.                 
  600.                 AdjustCamera(theDocument,
  601.                     theWindow->portRect.right - theWindow->portRect.left,
  602.                     theWindow->portRect.bottom - theWindow->portRect.top);
  603.  
  604.             //    Draw everything into offscreen pixmap.
  605.             if (DrawOffscreen(theDocument)) {
  606.                 SetPort( theWindow ) ;
  607.                 InvalRect( &theWindow->portRect ) ;
  608.                 DrawOnscreen(theDocument);
  609.             } 
  610.         }    
  611.     }
  612.     return err ;
  613.     
  614. bail:
  615.     return(memFullErr);
  616. }
  617.  
  618. //-----------------------------------------------------------------------
  619. // A P P L E E V E N T   S E N D E R   R O U T I N E S . . .
  620. //-----------------------------------------------------------------------
  621. // These routines are used to send ourselves AppleEvents, this is useful 
  622. // for a number of reasons, ultimately it would help make us scriptable if
  623. // we implemented some of the OSL, also it's a big help for debugging drags.
  624. //
  625. // Its not really easy to do source level debugging of drag handlers and 
  626. // trackers.  By packaging up the information into an appleevent and sending
  627. // it to ourselves, we can to source level debugging of the drag in the AE 
  628. // handler.
  629.  
  630.  
  631. //----------------------------------------------------------------------------------//
  632. //    Send a Quit Application Apple Event to myself to terminate this app.        
  633.  
  634. void SendQuitApp( void )
  635. {
  636.     AppleEvent    myAppleEvent, reply;
  637.     
  638.     //    Create the Apple Event.
  639.     FailIfErr(AECreateAppleEvent( kCoreEventClass, 
  640.                                   kAEQuitApplication, 
  641.                                   &pSelfAddress,
  642.                                   kAutoGenerateReturnID, 
  643.                                   kAnyTransactionID, 
  644.                                   &myAppleEvent));
  645.                                   
  646.     //    Send the Apple Event.
  647.       FailIfErr(AESend( &myAppleEvent, 
  648.                         &reply, 
  649.                         kAENoReply+kAENeverInteract, 
  650.                         kAENormalPriority,
  651.                         kAEDefaultTimeout, 
  652.                         nil, 
  653.                         nil));
  654.                         
  655.       AEDisposeDesc(&myAppleEvent);                // Dispose of the Apple Event.
  656. } // SendQuitApp
  657.  
  658. //----------------------------------------------------------------------------------//
  659. //    Send a Open Document Application Apple Event to myself to open a document.        
  660.  
  661. void SendOpenDoc(FSSpec *myFSSpec)
  662. {
  663.      AppleEvent    myAppleEvent;
  664.     AppleEvent    defReply;
  665.     AEDescList    docList;
  666.  
  667.     OSErr         ignoreErr;
  668.     
  669.     myAppleEvent.dataHandle = nil;
  670.     docList.dataHandle  = nil;
  671.     defReply.dataHandle = nil;
  672.         
  673.     // Create empty list and add one file spec
  674.     FailIfErr(AECreateList(nil,0,false, &docList));
  675.     
  676.     FailIfErr(AEPutPtr(&docList,1,typeFSS,(Ptr)myFSSpec,sizeof(FSSpec)));
  677.         
  678.     FailIfErr(AECreateAppleEvent(    kCoreEventClass,
  679.                                     kAEOpenDocuments,
  680.                                     &pSelfAddress,
  681.                                     kAutoGenerateReturnID,
  682.                                     kAnyTransactionID,
  683.                                     &myAppleEvent));
  684.  
  685.     // Put Params into our event and send it
  686.  
  687.     FailIfErr(AEPutParamDesc( &myAppleEvent,
  688.                               keyDirectObject,
  689.                               &docList));
  690.  
  691.     FailIfErr(AESend( &myAppleEvent,
  692.                       &defReply,
  693.                       kAENoReply+kAENeverInteract,
  694.                       kAENormalPriority,
  695.                       kAEDefaultTimeout,
  696.                       nil,
  697.                       nil));
  698.         
  699.         
  700.     if (myAppleEvent.dataHandle) 
  701.         ignoreErr = AEDisposeDesc(&myAppleEvent);
  702.         
  703.     if (docList.dataHandle) 
  704.         ignoreErr = AEDisposeDesc(&docList);
  705.             
  706. }    // SendOpenDoc 
  707.  
  708. //----------------------------------------------------------------------------------//
  709. //    Send a Print Document Application Apple Event to myself to open a document.        
  710.  
  711.  
  712.  
  713.  
  714. void SendPrintDoc(FSSpec *myFSSpec)
  715. {
  716.      AppleEvent    myAppleEvent;
  717.     AppleEvent    defReply;
  718.     AEDescList    docList;
  719.  
  720.     OSErr         ignoreErr;
  721.     
  722.     myAppleEvent.dataHandle = nil;
  723.     docList.dataHandle  = nil;
  724.     defReply.dataHandle = nil;
  725.         
  726.     // Create empty list and add one file spec
  727.     FailIfErr(AECreateList(nil,0,false, &docList));
  728.     
  729.     FailIfErr(AEPutPtr(&docList,1,typeFSS,(Ptr)myFSSpec,sizeof(FSSpec)));
  730.         
  731.     FailIfErr(AECreateAppleEvent(    kCoreEventClass,
  732.                                     kAEPrintDocuments,
  733.                                     &pSelfAddress,
  734.                                     kAutoGenerateReturnID,
  735.                                     kAnyTransactionID,
  736.                                     &myAppleEvent));
  737.  
  738.     // Put Params into our event and send it
  739.  
  740.     FailIfErr(AEPutParamDesc( &myAppleEvent,
  741.                               keyDirectObject,
  742.                               &docList));
  743.  
  744.     FailIfErr(AESend( &myAppleEvent,
  745.                       &defReply,
  746.                       kAENoReply+kAENeverInteract,
  747.                       kAENormalPriority,
  748.                       kAEDefaultTimeout,
  749.                       nil,
  750.                       nil));
  751.         
  752.         
  753.     if (myAppleEvent.dataHandle) 
  754.         ignoreErr = AEDisposeDesc(&myAppleEvent);
  755.         
  756.     if (docList.dataHandle) 
  757.         ignoreErr = AEDisposeDesc(&docList);
  758.             
  759. }    // SendOpenDoc 
  760.  
  761.  
  762.  
  763. //----------------------------------------------------------------------------------
  764. //    Send a drag receive Apple Event to myself to handle the receipt of a drag.        
  765.  
  766.  
  767. void SendDragRecv( myPrivateDataHdl privateHdl )
  768. {
  769.      AppleEvent    myAppleEvent;
  770.     AppleEvent    defReply;
  771.  
  772.     OSErr         ignoreErr;
  773.     
  774.     ProcessSerialNumber        myPSN ;
  775.     
  776.     AEDesc            myAddress ;
  777.     char            cMemTags = HGetState((Handle)privateHdl);    // save the state of the handle in case
  778.                                                                 // it was already locked before we were
  779.                                                                 // called
  780.     
  781.     myAppleEvent.dataHandle = nil;
  782.     defReply.dataHandle = nil;
  783.  
  784.     // the static pSelfAddress that we create an usually use will cause the 
  785.     // AE handler to be caused directly (less overhead).  We DON'T WANT THAT
  786.     // to happen here.  The reason being that the handler for this event needs
  787.     // to be called in our main event loop, not directly at the send.  Doing things
  788.     // this way lets us get out of the Drag Managers context, back into our own.
  789.     // that in turn lets us use a high level debugger.
  790.     
  791.     
  792.     FailIfErr(GetCurrentProcess(&myPSN)) ;
  793.     FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&myPSN,sizeof(ProcessSerialNumber),&myAddress));
  794.  
  795.     FailIfErr(AECreateAppleEvent(    kDraggingClass,
  796.                                     kDragReceiveID,
  797.                                     &myAddress,
  798.                                     kAutoGenerateReturnID,
  799.                                     kAnyTransactionID,
  800.                                     &myAppleEvent));
  801.  
  802.     // lock down the handle
  803.     MoveHHi( (Handle)privateHdl );
  804.     HLock( (Handle)privateHdl );
  805.     
  806.     // Put Params into our event and send it
  807.  
  808.     FailIfErr(AEPutParamPtr( &myAppleEvent,
  809.                              keyPrivateData,
  810.                              typeChar,
  811.                              *privateHdl,
  812.                              GetHandleSize( (Handle)privateHdl )));
  813.  
  814.     // restore the state of the handle (effectively the same as HUnlock)
  815.     HSetState((Handle)privateHdl, cMemTags) ;
  816.  
  817.     FailIfErr(AESend( &myAppleEvent,
  818.                       &defReply,
  819.                       kAENoReply+kAENeverInteract,
  820.                       kAENormalPriority,
  821.                       kAEDefaultTimeout,
  822.                       nil,
  823.                       nil));
  824.         
  825.         
  826.     if (myAddress.dataHandle) 
  827.         ignoreErr = AEDisposeDesc(&myAddress);
  828.  
  829.     if (myAppleEvent.dataHandle) 
  830.         ignoreErr = AEDisposeDesc(&myAppleEvent);
  831. }